package com.local.videoplayer.ads;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.facebook.ads.Ad;
import com.facebook.ads.AdError;
import com.facebook.ads.AdSettings;
import com.facebook.ads.InterstitialAdListener;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.jaaksi.superclean.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class AdmobUtil {

    private static final int LOADING_AD_DELAY = 800;
    private static final int CANCEL_AD = 0x1000;

    private Context context;
    private Activity currentActivity;

    // loading view
    private View loadingAdView = null;
    private TextView loadingTextView = null;
    private ProgressWheel loadingProgressWheel = null;

    private List<String> testDeviceList = new ArrayList<>();
    private List<InterstitialAd> adList = new ArrayList<>();
    private List<InterstitialAd> cacheAdList = new ArrayList<>();

    private List<String> noAdActivityList = new ArrayList<>();
    private List<String> noAdCheckActivityList = new ArrayList<>();

    public boolean isActive = false;            // is activity is active on foreground

    // flags
    public boolean isShouldShowAdmob = true;   // when ad is shown, it will be false. get avoid of duplicated pop up.
    public boolean isAdmobCancelled = false;    // loading spends more than 5 seconds, abandon this request.
    public boolean isInShowingChain = false;    // display chain is working.
    public boolean isInCachingChain = false;    // loading chain is working.
    public boolean isShowingAdMob = false;      // ad opened
    public boolean isStopAd = false;            // stop ad
    public boolean isFromExternalActivity = false;            // stop ad once

    private InterstitialAd currentCachedAd;

    Timer cancelTimer = null;
    Handler timerHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (isActive && isInShowingChain) {
                if (msg.what == CANCEL_AD) {
                    // dismiss load ad view, and abandon this ad
                    isAdmobCancelled = true;
                    removeLoadingView();
                }
            }
            super.handleMessage(msg);
        }
    };

    private static AdmobUtil instance = null;

    public static synchronized AdmobUtil getInstance() {
        if (instance == null) {
            instance = new AdmobUtil();
        }
        return instance;
    }

    private AdmobUtil() {
    }


    //****************************** INIT ****************************** //

    public AdmobUtil init(Application application) {
        this.context = application.getApplicationContext();
        application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            }

            @Override
            public void onActivityStarted(Activity activity) {
                if (noAdCheckActivityList.contains(activity.getClass().getName()))
                    return;

                if (noAdActivityList.contains(activity.getClass().getName())) {
                    isStopAd = true;
                } else {
                    isStopAd = false;
                }
            }

            @Override
            public void onActivityResumed(Activity activity) {
                if (noAdCheckActivityList.contains(activity.getClass().getName()))
                    return;

                removeLoadingView();
                if (!isActive) {
                    //app 从后台唤醒，进入前台
                    isActive = true;
                    if (!isStopAd && isShowingAdMob == false) {
                        currentActivity = activity;
                        if (isFromExternalActivity)
                            isFromExternalActivity = false;
                        else
                            displayAd();
//                        displayAd("10000 关闭", 10000);
                    }
                }
            }

            @Override
            public void onActivityPaused(Activity activity) {
            }

            @Override
            public void onActivityStopped(Activity activity) {
                if (noAdCheckActivityList.contains(activity.getClass().getName()))
                    return;

                if (!isAppOnForeground()) {
                    // app 进入后台
                    // 全局变量isActive = false 记录当前已经进入后台
                    isActive = false;
                }
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
        loadingAdView = LayoutInflater.from(context).inflate(R.layout.admob_ad, null);
        loadingTextView = (TextView) loadingAdView.findViewById(R.id.title);
        loadingProgressWheel = (ProgressWheel) loadingAdView.findViewById(R.id.progress);
        return this;
    }

    public AdmobUtil addAdmob(String unitId) {
        // add display ad
        final InterstitialAd adForDisplay = new InterstitialAd(context);
        adForDisplay.setAdUnitId(unitId);
        adForDisplay.setAdListener(new AdListener() {
            public void onAdLoaded() {
                if (cancelTimer != null) {
                    try {
                        cancelTimer.cancel();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (isShouldShowAdmob == true) {
                    if (isAdmobCancelled) {
                        removeLoadingView();
                        isAdmobCancelled = false;
                        currentCachedAd = adForDisplay;
                    } else {
                        isShouldShowAdmob = false;
                        if (isActive == true && isShowingAdMob == false) {
                            addLoadingView();
                            new Handler().postDelayed(new Runnable() {
                                public void run() {
                                    showAd(adForDisplay);
                                }
                            }, LOADING_AD_DELAY);
                        } else {
                            removeLoadingView();
                            currentCachedAd = adForDisplay;
                        }
                    }
                }
                isInShowingChain = false;
            }

            public void onAdFailedToLoad(int errorCode) {
                if (isAdmobCancelled) {
                    isAdmobCancelled = false;
                    isInShowingChain = false;
                    loadAndCacheAd();
                } else {
                    int nextIndex = adList.indexOf(adForDisplay) + 1;
                    if (nextIndex < adList.size()) {
                        // load next.
                        loadAd(adList.get(nextIndex));
                    } else {
                        //the last ad operation.
                        isShouldShowAdmob = false;
                        isInShowingChain = false;
                        removeLoadingView();

                        if (facebookPlacementId.equals("")) {
                            loadAndCacheAd();
                        } else {
                            showFacebookAdNow(context);
                        }
                    }
                }
            }

            public void onAdLeftApplication() {

            }

            public void onAdOpened() {
                adOpened();
            }

            public void onAdClosed() {
                adClosed();
            }
        });
        adList.add(adForDisplay);

        // add cache ad
        final InterstitialAd adForCache = new InterstitialAd(context);
        adForCache.setAdUnitId(unitId);
        adForCache.setAdListener(new AdListener() {
            public void onAdLoaded() {
                currentCachedAd = adForCache;
                isInCachingChain = false;
            }

            public void onAdFailedToLoad(int errorCode) {
                int nextIndex = cacheAdList.indexOf(adForCache) + 1;
                if (nextIndex < cacheAdList.size()) {
                    // load next.
                    loadAd(cacheAdList.get(nextIndex));
                } else {
                    //the last ad operation.
                    isInCachingChain = false;
                    isShowingAdMob = false;
                    isInShowingChain = false;
                }
            }

            public void onAdLeftApplication() {
            }

            public void onAdOpened() {
                adOpened();
            }

            public void onAdClosed() {
                adClosed();
            }
        });
        cacheAdList.add(adForCache);
        return this;
    }

    public AdmobUtil addNoAdActiviy(String action) {
        noAdActivityList.add(action);
        return this;
    }

    public AdmobUtil addNoAdCheckActiviy(String action) {
        noAdCheckActivityList.add(action);
        return this;
    }

    public AdmobUtil addTestDevice(String testDevice) {
        if (!testDeviceList.contains(testDevice))
            testDeviceList.add(testDevice);
        return this;
    }

    private void loadAd(InterstitialAd ad) {
        try {
            AdRequest.Builder builder = new AdRequest.Builder();
            if (testDeviceList != null) {
                for (String testDevice : testDeviceList)
                    builder.addTestDevice(testDevice);
            }
            ad.loadAd(builder.build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //****************************** FOR DISPLAY ****************************** //

    private void showAd(InterstitialAd ad) {
        try {
            if (isActive == true && isShowingAdMob == false) {
                ad.show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void adOpened() {
        isShowingAdMob = true;
        isShouldShowAdmob = false;
        isInShowingChain = false;
        removeLoadingView();
    }


    private void adClosed() {
        isShowingAdMob = false;
        isInShowingChain = false;
        loadAndCacheAd();
    }


    public void addLoadingView() {
        try {
            ViewGroup rootView = (ViewGroup) currentActivity.findViewById(android.R.id.content);
            if (rootView.indexOfChild(loadingAdView) < 0) {
                rootView.addView(loadingAdView);
                loadingProgressWheel.spin();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void removeLoadingView() {
        try {
            loadingProgressWheel.stopSpinning();
            ViewGroup rootView = (ViewGroup) currentActivity.findViewById(android.R.id.content);
            rootView.removeView(loadingAdView);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // start display chain
    public void displayAd() {
        displayAd(null);
    }

    public void displayAd(String loadingText) {
        isShouldShowAdmob = true;
        if (isActive == true && isShowingAdMob == false) {
            if (currentCachedAd != null && currentCachedAd.isLoaded()) {
                if (loadingText != null && !"".equals(loadingText)) {
                    loadingTextView.setText(loadingText);
                    loadingTextView.setVisibility(View.VISIBLE);
                } else {
//                    loadingTextView.setVisibility(View.GONE);
                }
                addLoadingView();
                new Handler().postDelayed(new Runnable() {
                    public void run() {
                        showAd(currentCachedAd);
                        currentCachedAd = null;
                    }
                }, LOADING_AD_DELAY);
            } else {
                isInShowingChain = true;
                if (adList != null && adList.size() > 0) {
                    loadAd(adList.get(0));
                } else {
                    showFacebookAdNow(context);
                }
            }
        }
    }

    public void displayAd(String loadingText, int maxTimeLimit) {
        if (isActive == true && isShowingAdMob == false && isInShowingChain == false) {
            addLoadingView();
            cancelTimer = new Timer();
            cancelTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    Message message = new Message();
                    message.what = 3;
                    timerHandler.sendMessage(message);
                }
            }, maxTimeLimit);
            displayAd(loadingText);
        }
    }

    // start cache chain
    public void loadAndCacheAd() {
        if (currentCachedAd == null && isInCachingChain == false) {
            isInCachingChain = true;
            if (cacheAdList != null && cacheAdList.size() > 0) {
                loadAd(cacheAdList.get(0));
            }
        }
    }

    public boolean isAppOnForeground() {
        // Returns a list of application processes that are running on the
        // device
        ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = context.getApplicationContext().getPackageName();
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            // The name of the process that this object is associated with.
            if (appProcess.processName.equals(packageName)
                    && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true;
            }
        }
        return false;
    }


    public void showFacebookAd(com.facebook.ads.InterstitialAd ad) {
        try {
            if (isActive == true && isShowingAdMob == false) {
                ad.show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private String facebookPlacementId = "";

    public AdmobUtil setFacebookPlacementId(String facebookPlacementId) {
        this.facebookPlacementId = facebookPlacementId;
        return this;
    }

    public void showFacebookAdNow(Context context) {
        if (facebookPlacementId == null || facebookPlacementId.equals(""))
            if (testDeviceList != null)
                for (String testDevice : testDeviceList) {
                    AdSettings.addTestDevice(testDevice);
                }


//        AdSettings.addTestDevice("826E10B6C79A23DD31E773D7CA370064");
        final com.facebook.ads.InterstitialAd interstitialAd = new com.facebook.ads.InterstitialAd(context, facebookPlacementId);
        interstitialAd.setAdListener(new InterstitialAdListener() {
            @Override
            public void onInterstitialDisplayed(Ad ad) {
                adOpened();
            }

            @Override
            public void onInterstitialDismissed(Ad ad) {
                adClosed();
            }

            @Override
            public void onError(Ad ad, AdError adError) {
                loadAndCacheAd();
            }

            @Override
            public void onAdLoaded(final Ad ad) {
                addLoadingView();
                new Handler().postDelayed(new Runnable() {
                    public void run() {
                        showFacebookAd((com.facebook.ads.InterstitialAd) ad);
                    }
                }, LOADING_AD_DELAY);
            }

            @Override
            public void onAdClicked(Ad ad) {

            }

            @Override
            public void onLoggingImpression(Ad ad) {

            }
        });
        interstitialAd.loadAd();
    }
}
